﻿#include "GuideManager.h"
#include <QPainter>
#include <QPainterPath>
#include <QMouseEvent>
#include <QApplication>
#include <QGraphicsOpacityEffect>
#include <QVBoxLayout>
#include <QPushButton>
#include <QKeyEvent>
#include <QTimer>

#define COLOR_TARGET_AREA  QColor(0, 0, 0, 5)
#define COLOR_OTHER_AREA   QColor(0, 0, 0, 150)


GuideManager::GuideManager(QWidget *parent)
    : QWidget(parent)
{
    setAttribute(Qt::WA_NoSystemBackground);
    setAttribute(Qt::WA_TranslucentBackground);
    setWindowFlags(Qt::FramelessWindowHint | Qt::Tool);
    setAttribute(Qt::WA_TransparentForMouseEvents, false);

    if (parent) {
        setGeometry(parent->geometry());
        parent->installEventFilter(this);
    }

    m_bubble = new GuideBubble(this);
    m_bubble->hide();

    connect(m_bubble, &GuideBubble::prevRequested, this, [this](){
        m_currentIndex--;
        safeShowStep();
    });
    connect(m_bubble, &GuideBubble::nextRequested, this, [this](){
        m_currentIndex++;
        safeShowStep();
    });
    connect(m_bubble, &GuideBubble::doneRequested, this, [this](){
        hide();
        emit finished();
    });
}

GuideManager::~GuideManager() {}

void GuideManager::addStep(QWidget *widget, const QString &text, GuideStepBefore_fn before)
{
    if (!widget) return;
    m_steps.append({widget, text, before});
}

void GuideManager::start()
{
    if (m_steps.isEmpty()) return;
    m_bubble->setStepCount(m_steps.length());
    m_currentIndex = 0;
    showCurrentStep();
    show();
    raise();
}

void GuideManager::showEvent(QShowEvent *event)
{
    QWidget::showEvent(event);
    activateWindow();     // 让窗口成为活动窗口
    setFocusPolicy(Qt::StrongFocus);
    setFocus(); // 启动时抢占焦点，才能接收键盘输入
}

void GuideManager::resizeEvent(QResizeEvent *e)
{
    if (parentWidget()) {
        setGeometry(parentWidget()->geometry());
    }
    QWidget::resizeEvent(e);
}

void GuideManager::keyPressEvent(QKeyEvent *event)
{
    switch (event->key()) {
    case Qt::Key_Right:
    case Qt::Key_Down:
    case Qt::Key_Space:
        m_currentIndex++;
        break;
    case Qt::Key_Left:
    case Qt::Key_Up:
        m_currentIndex--;
        break;
    case Qt::Key_Escape:
        hide();
        emit finished();
        return;
    default:
        QWidget::keyPressEvent(event);
        return;
    }

    safeShowStep();
}

void GuideManager::safeShowStep()
{
    if (m_currentIndex < 0)
        m_currentIndex = 0;
    if (m_currentIndex >= m_steps.size()) {
        hide();
        emit finished();
        return;
    }
    showCurrentStep();
}

void GuideManager::showCurrentStep()
{
    if (m_currentIndex < 0 || m_currentIndex >= m_steps.size()) {
        hide();
        emit finished();
        return;
    }

    auto &step = m_steps[m_currentIndex];
    // 前置回调函数
    if (step.onBeforeStep) step.onBeforeStep();

    m_highlightRect = targetRectFor(step.targetWidget);

    // 设置提示气泡内容
    m_bubble->setText(step.text);
    // 设置当前步骤数
    m_bubble->setCurrentStep(m_currentIndex + 1);

    // 这样可以防止尺寸调整失败
    QTimer::singleShot(0, this, &GuideManager::moveToFinePos);

    update();
}

void GuideManager::moveToFinePos()
{
    if (m_isFirstShowBubble) {
        m_bubble->setAnimationEnabled(false);
        m_isFirstShowBubble = false;
    } else {
        m_bubble->setAnimationEnabled(true);
    }

    m_bubble->adjustSize();

    // 设置气泡的弹出位置，默认位置在下方显示
    int px = geometry().x() + m_highlightRect.x() + 2;
    int py = geometry().y() + m_highlightRect.y() + m_highlightRect.height() + 2;

    if (m_highlightRect.height() > 1.6 * m_bubble->height() && m_highlightRect.width() > 1.6 * m_bubble->width()) {
        // 高亮区域足够大就在高亮区域正中间显示气泡
        px = geometry().x() + m_highlightRect.x() + (m_highlightRect.width() - m_bubble->width()) / 2;
        py = geometry().y() + m_highlightRect.y() + (m_highlightRect.height() - m_bubble->height()) / 2;
    } else if (m_highlightRect.y() + m_highlightRect.height() + m_bubble->height() < height()) {
        // 下方空间足够大，在高亮区域下方
        // px = geometry().x() + m_highlightRect.x() + 2;
        // py = geometry().y() + m_highlightRect.y() + m_highlightRect.height() + 2;
    } else if (m_highlightRect.x() + m_highlightRect.width() + m_bubble->width() < width()) {
        // 右侧空间足够大，在高亮区域右侧
        px = geometry().x() + m_highlightRect.x() + m_highlightRect.width() + 2;
        py = geometry().y() + m_highlightRect.y() + 2;
    } else if (m_bubble->width() < m_highlightRect.x()) {
        // 左侧空间足够大，在高亮区域左侧
        px = geometry().x() + m_highlightRect.x() - m_bubble->width() - 2;
        py = geometry().y() + m_highlightRect.y() + 2;
    } else if (m_bubble->height() < m_highlightRect.y()) {
        // 上方空间足够大，在高亮区域上方
        px = geometry().x() + m_highlightRect.x() + 2;
        py = geometry().y() + m_highlightRect.y() - m_bubble->height() - 2;
    }
    m_bubble->move(px, py);

    m_bubble->show();
}

QRect GuideManager::targetRectFor(QWidget *widget)
{
    if (!widget) return QRect();
    QPoint globalPos = widget->mapTo(parentWidget(), QPoint(0, 0));
    return QRect(globalPos, widget->size());
}

void GuideManager::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    p.setRenderHint(QPainter::Antialiasing);

    p.fillRect(rect(), COLOR_TARGET_AREA);

    // 挖空高亮区域
    QPainterPath maskPath;
    maskPath.addRect(rect());

    // 在目标区域挖空（即反向路径）
    QPainterPath holePath;
    holePath.addRoundedRect(m_highlightRect, 8, 8);
    maskPath -= holePath;

    // 用半透明颜色填充遮罩
    p.setCompositionMode(QPainter::CompositionMode_SourceOver);
    p.fillPath(maskPath, COLOR_OTHER_AREA);
}

void GuideManager::mousePressEvent(QMouseEvent *event)
{
    Q_UNUSED(event);
    m_currentIndex++;
    showCurrentStep();
}


bool GuideManager::eventFilter(QObject *watched, QEvent *event)
{
    if (parentWidget() && watched == parentWidget() &&
            (event->type() == QEvent::Resize || event->type() == QEvent::Move)) {
        setGeometry(parentWidget()->geometry());
        showCurrentStep();
    }
    return QWidget::eventFilter(watched, event);
}
